001 /*
002 * Copyright 2003-2005 The Apache Software Foundation
003 * Copyright 2005 Stephen McConnell
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package net.dpml.cli.builder;
018
019 import java.util.ArrayList;
020 import java.util.List;
021
022 import net.dpml.cli.Argument;
023 import net.dpml.cli.option.ArgumentImpl;
024 import net.dpml.cli.resource.ResourceConstants;
025 import net.dpml.cli.resource.ResourceHelper;
026 import net.dpml.cli.validation.Validator;
027
028 /**
029 * Builds Argument instances.
030 *
031 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
032 * @version 1.0.0
033 */
034 public class ArgumentBuilder
035 {
036 /** i18n */
037 private static final ResourceHelper RESOURCES = ResourceHelper.getResourceHelper();
038
039 /** name of the argument. Used for display and lookups in CommandLine */
040 private String m_name;
041
042 /** description of the argument. Used in the automated online help */
043 private String m_description;
044
045 /** minimum number of values required */
046 private int m_minimum;
047
048 /** maximum number of values permitted */
049 private int m_maximum;
050
051 /** character used to separate the values from the option */
052 private char m_initialSeparator;
053
054 /** character used to separate the values from each other */
055 private char m_subsequentSeparator;
056
057 /** object that should be used to ensure the values are valid */
058 private Validator m_validator;
059
060 /** used to identify the consume remaining option, typically "--" */
061 private String m_consumeRemaining;
062
063 /** default values for argument */
064 private List m_defaultValues;
065
066 /** id of the argument */
067 private int m_id;
068
069 /**
070 * Creates a new ArgumentBuilder instance
071 */
072 public ArgumentBuilder()
073 {
074 reset();
075 }
076
077 /**
078 * Creates a new Argument instance using the options specified in this
079 * ArgumentBuilder.
080 *
081 * @return A new Argument instance using the options specified in this
082 * ArgumentBuilder.
083 */
084 public final Argument create()
085 {
086 final Argument argument =
087 new ArgumentImpl(
088 m_name,
089 m_description,
090 m_minimum,
091 m_maximum,
092 m_initialSeparator,
093 m_subsequentSeparator,
094 m_validator,
095 m_consumeRemaining,
096 m_defaultValues,
097 m_id );
098 reset();
099 return argument;
100 }
101
102 /**
103 * Resets the ArgumentBuilder to the defaults for a new Argument. The
104 * method is called automatically at the end of a create() call.
105 * @return the argument builder
106 */
107 public final ArgumentBuilder reset()
108 {
109 m_name = "arg";
110 m_description = null;
111 m_minimum = 0;
112 m_maximum = Integer.MAX_VALUE;
113 m_initialSeparator = ArgumentImpl.DEFAULT_INITIAL_SEPARATOR;
114 m_subsequentSeparator = ArgumentImpl.DEFAULT_SUBSEQUENT_SEPARATOR;
115 m_validator = null;
116 m_consumeRemaining = "--";
117 m_defaultValues = null;
118 m_id = 0;
119 return this;
120 }
121
122 /**
123 * Sets the name of the argument. The name is used when displaying usage
124 * information and to allow lookups in the CommandLine object.
125 *
126 * @see net.dpml.cli.CommandLine#getValue(String)
127 *
128 * @param newName the name of the argument
129 * @return this ArgumentBuilder
130 */
131 public final ArgumentBuilder withName( final String newName )
132 {
133 if( newName == null )
134 {
135 throw new IllegalArgumentException(
136 RESOURCES.getMessage(
137 ResourceConstants.ARGUMENT_BUILDER_NULL_NAME ) );
138 }
139 if( "".equals( newName ) )
140 {
141 throw new IllegalArgumentException(
142 RESOURCES.getMessage(
143 ResourceConstants.ARGUMENT_BUILDER_EMPTY_NAME ) );
144 }
145 m_name = newName;
146 return this;
147 }
148
149 /**
150 * Sets the description of the argument.
151 *
152 * The description is used when displaying online help.
153 *
154 * @param newDescription a description of the argument
155 * @return this ArgumentBuilder
156 */
157 public final ArgumentBuilder withDescription( final String newDescription )
158 {
159 m_description = newDescription;
160 return this;
161 }
162
163 /**
164 * Sets the minimum number of values needed for the argument to be valid.
165 *
166 * @param newMinimum the number of values needed
167 * @return this ArgumentBuilder
168 */
169 public final ArgumentBuilder withMinimum( final int newMinimum )
170 {
171 if( newMinimum < 0 )
172 {
173 throw new IllegalArgumentException(
174 RESOURCES.getMessage(
175 ResourceConstants.ARGUMENT_BUILDER_NEGATIVE_MINIMUM ) );
176 }
177 m_minimum = newMinimum;
178 return this;
179 }
180
181 /**
182 * Sets the maximum number of values allowed for the argument to be valid.
183 *
184 * @param newMaximum the number of values allowed
185 * @return this ArgumentBuilder
186 */
187 public final ArgumentBuilder withMaximum( final int newMaximum )
188 {
189 if( newMaximum < 0 )
190 {
191 throw new IllegalArgumentException(
192 RESOURCES.getMessage(
193 ResourceConstants.ARGUMENT_BUILDER_NEGATIVE_MAXIMUM ) );
194 }
195 m_maximum = newMaximum;
196 return this;
197 }
198
199 /**
200 * Sets the character used to separate the values from the option. When an
201 * argument is of the form -libs:dir1,dir2,dir3 the initialSeparator would
202 * be ':'.
203 *
204 * @param newInitialSeparator the character used to separate the values
205 * from the option
206 * @return this ArgumentBuilder
207 */
208 public final ArgumentBuilder withInitialSeparator(
209 final char newInitialSeparator )
210 {
211 m_initialSeparator = newInitialSeparator;
212 return this;
213 }
214
215 /**
216 * Sets the character used to separate the values from each other. When an
217 * argument is of the form -libs:dir1,dir2,dir3 the subsequentSeparator
218 * would be ','.
219 *
220 * @param newSubsequentSeparator the character used to separate the values
221 * from each other
222 * @return this ArgumentBuilder
223 */
224 public final ArgumentBuilder withSubsequentSeparator(
225 final char newSubsequentSeparator )
226 {
227 m_subsequentSeparator = newSubsequentSeparator;
228 return this;
229 }
230
231 /**
232 * Sets the validator instance used to perform validation on the Argument
233 * values.
234 *
235 * @param newValidator a Validator instance
236 * @return this ArgumentBuilder
237 */
238 public final ArgumentBuilder withValidator( final Validator newValidator )
239 {
240 if( newValidator == null )
241 {
242 throw new IllegalArgumentException(
243 RESOURCES.getMessage(
244 ResourceConstants.ARGUMENT_BUILDER_NULL_VALIDATOR ) );
245 }
246 m_validator = newValidator;
247 return this;
248 }
249
250 /**
251 * Sets the "consume remaining" option, defaults to "--". Use this if you
252 * want to allow values that might be confused with option strings.
253 *
254 * @param newConsumeRemaining the string to use for the consume
255 * remaining option
256 * @return this ArgumentBuilder
257 */
258 public final ArgumentBuilder withConsumeRemaining( final String newConsumeRemaining )
259 {
260 if( newConsumeRemaining == null )
261 {
262 throw new IllegalArgumentException(
263 RESOURCES.getMessage(
264 ResourceConstants.ARGUMENT_BUILDER_NULL_CONSUME_REMAINING ) );
265 }
266 if( "".equals( newConsumeRemaining ) )
267 {
268 throw new IllegalArgumentException(
269 RESOURCES.getMessage(
270 ResourceConstants.ARGUMENT_BUILDER_EMPTY_CONSUME_REMAINING ) );
271 }
272 m_consumeRemaining = newConsumeRemaining;
273 return this;
274 }
275
276 /**
277 * Sets the default value.
278 *
279 * @param defaultValue the default value for the Argument
280 * @return this ArgumentBuilder
281 */
282 public final ArgumentBuilder withDefault( final Object defaultValue )
283 {
284 if( defaultValue == null )
285 {
286 throw new IllegalArgumentException(
287 RESOURCES.getMessage(
288 ResourceConstants.ARGUMENT_BUILDER_NULL_DEFAULT ) );
289 }
290
291 if( m_defaultValues == null )
292 {
293 m_defaultValues = new ArrayList( 1 );
294 }
295 m_defaultValues.add( defaultValue );
296 return this;
297 }
298
299 /**
300 * Sets the default values.
301 *
302 * @param newDefaultValues the default values for the Argument
303 * @return this ArgumentBuilder
304 */
305 public final ArgumentBuilder withDefaults( final List newDefaultValues )
306 {
307 if( newDefaultValues == null )
308 {
309 throw new IllegalArgumentException(
310 RESOURCES.getMessage(
311 ResourceConstants.ARGUMENT_BUILDER_NULL_DEFAULTS ) );
312 }
313 m_defaultValues = newDefaultValues;
314 return this;
315 }
316
317 /**
318 * Sets the id
319 *
320 * @param newId the id of the Argument
321 * @return this ArgumentBuilder
322 */
323 public final ArgumentBuilder withId( final int newId )
324 {
325 m_id = newId;
326 return this;
327 }
328 }